package dao

import (
	"errors"
	"log"
	"micro.user.auth.server/common"
	"time"

	"github.com/dgrijalva/jwt-go"

	"micro.user.auth.server/config"
)

func GenerateToken(userId uint64, key map[string]interface{}) (string, error) {
	var k jwt.MapClaims
	k = key

	token := jwt.NewWithClaims(
		jwt.SigningMethodHS256,
		k,
	)

	t, err := token.SignedString(config.SecretKey)
	if err != nil {
		return "", err
	}

	return t, nil
}

func CheckToken(userId uint64, token string) (bool, error) {
	t, err := jwt.Parse(token, func(tk *jwt.Token) (interface{}, error) {
		if _, ok := tk.Method.(*jwt.SigningMethodHMAC); !ok {
			return nil, errors.New("Unexpected signing method error")
		}
		return config.SecretKey, nil
	})
	if err != nil {
		return false, err
	}

	claim, ok := t.Claims.(jwt.MapClaims)
	if !ok || !t.Valid {
		return false, common.TokenIsInValid
	}
	log.Printf("claim:%+v", claim)
	log.Printf("claim exp:%.0f, iat:%.0f", claim["Expiration"], claim["TimeNow"])

	return true, nil
}

func ResolveToken(userId uint64, token string) (map[string]interface{}, error) {
	t, err := jwt.Parse(token, func(tk *jwt.Token) (interface{}, error) {
		if _, ok := tk.Method.(*jwt.SigningMethodHMAC); !ok {
			return nil, errors.New("Unexpected signing method error")
		}
		return config.SecretKey, nil
	})
	if err != nil {
		return nil, err
	}

	claim, ok := t.Claims.(jwt.MapClaims)
	if !ok || !t.Valid {
		return nil, common.TokenIsInValid
	}

	log.Printf("claim:%+v", claim)
	return claim, nil
}

func RefreshToken(userId uint64, token string) (string, error) {
	t, err := jwt.Parse(token, func(tk *jwt.Token) (interface{}, error) {
		if _, ok := tk.Method.(*jwt.SigningMethodHMAC); !ok {
			return nil, errors.New("Unexpected signing method error")
		}
		return config.SecretKey, nil
	})
	if err != nil {
		return "", err
	}

	claim, ok := t.Claims.(jwt.MapClaims)
	if !ok || !t.Valid {
		return "", errors.New("token is not valid")
	}
	log.Printf("claim:%+v", claim)
	log.Printf("claim exp:%.0f, iat:%.0f", claim["exp"], claim["iat"])

	claim["exp"] = time.Now().Add(time.Minute * 5).Unix()

	ta := jwt.NewWithClaims(
		jwt.SigningMethodHS256,
		claim,
	)

	tt, err := ta.SignedString(config.SecretKey)
	if err != nil {
		return "", err
	}
	log.Printf("tt:%+v", tt)

	return tt, nil
}
